﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AFCEPF.BankApplication.BLL
{
    /// <summary>
    /// The Bank (!)
    /// </summary>
    public class Bank : Singleton<Bank>
    {
        

        private readonly AccountList2<AccountBase>  _accounts;
        private DecisionChain                       _decisionChain;

        

        /**********************************************************************
         * Ctor.
         *********************************************************************/


        /// <summary>
        /// Private constructor that prevents
        /// instanciation from outside the class.
        /// </summary>
        private Bank()
        {
            _accounts = new AccountList2<AccountBase>();

            _decisionChain = new DecisionChain();

        }

        

        public DecisionChain DecisionChain
        {
            get { return _decisionChain;    }
            
        }

        /**********************************************************************
         * Methods.
         *********************************************************************/

        /// <summary>
        /// Gets the total funds hosted in the Bank.
        /// </summary>
        /// <returns>the total funds hosted in the Bank</returns>
        public double GetTotalFunds()
        {
            return _accounts.Sum(account => account.Balance);

            //var query = (from account in _accounts
            //             select account.Balance).Sum();
            //return query;
        }


        /// <summary>
        /// Gets the total overdrawn amount.
        /// </summary>
        /// <returns></returns>
        public double GetTotalOverdrawnAmount()
        {
            var query = (from account in _accounts
                            where account.Balance < 0
                                select account.Balance).Sum();

            var x = _accounts.Sum(account => account.Balance);
            return query;
        }


        /// <summary>
        /// Called when a withdrawal is performed over 
        /// and account whose balance is negative.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">
        /// The <see cref="AFCEPF.BankApplication.BLL.AccountEventArgs"/> instance 
        /// containing the event data.</param>
        internal void OnAccountNegativeBalanceWithdraw(object sender, AccountEventArgs e)
        {
            // On instancie le IVisitor qui va prélever 
            // 1 % du montant du découvert, sur chacun
            // des retraits effectués sur un compte 
            // à découvert..
            IVisitor visitor = new NegativeBalanceTaxVisitor();

            // On récupère le compte déclencheur de l'event..
            //AccountBase account = sender as AccountBase;
            // mais plutôt :
            IVisitable account = sender as IVisitable;

            // On dit au compte d'accepter le visiteur, 
            // qui, à son tour, effectue son traitement..
            if (account != null) account.Accept(visitor);
        }

        /// <summary>
        /// Called when a withdrawal exceeding the account's
        /// overdrawn limit is performed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="AFCEPF.BankApplication.BLL.AccountEventArgs"/> instance containing the event data.</param>
        internal void OnOverLimitWithdraw(object sender, AccountEventArgs e)
        {
               
        }


        /**********************************************************************
         * Properties.
         *********************************************************************/
        
        /// <summary>
        /// Gets the accounts.
        /// </summary>     
        public AccountList2<AccountBase> Accounts
        {
            get { return _accounts;  }            
        }

        


    }
}
